interface FetchOptions extends RequestInit {
  retries?: number;
  retryDelay?: number;
}

interface FetchResponse<T> {
  data: T;
  status: number;
  ok: boolean;
}

/**
 * 带重试机制的 fetch 请求封装
 * @param url 请求地址
 * @param options 请求配置
 * @returns Promise<FetchResponse<T>>
 */
export async function fetchWithRetry<T>(
  url: string,
  options: FetchOptions = {}
): Promise<FetchResponse<T>> {
  const {
    retries = 3,
    retryDelay = 1000,
    ...fetchOptions
  } = options;

  let lastError: Error | null = null;

  for (let i = 0; i <= retries; i++) {
    try {
      const response = await fetch(url, fetchOptions);
      const data = await response.json();

      return {
        data,
        status: response.status,
        ok: response.ok,
      };
    } catch (error) {
      lastError = error as Error;
      
      if (i === retries) {
        break;
      }

      // 等待指定的延迟时间后重试
      await new Promise(resolve => setTimeout(resolve, retryDelay));
    }
  }

  throw new Error(`请求失败，已重试 ${retries} 次: ${lastError?.message}`);
}

/**
 * GET 请求封装
 */
export async function get<T>(
  url: string,
  options: FetchOptions = {}
): Promise<FetchResponse<T>> {
  return fetchWithRetry<T>(url, {
    method: 'GET',
    ...options,
  });
}

/**
 * POST 请求封装
 */
export async function post<T>(
  url: string,
  data: unknown,
  options: FetchOptions = {}
): Promise<FetchResponse<T>> {
  return fetchWithRetry<T>(url, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      ...options.headers,
    },
    body: JSON.stringify(data),
    ...options,
  });
}

/**
 * PUT 请求封装
 */
export async function put<T>(
  url: string,
  data: unknown,
  options: FetchOptions = {}
): Promise<FetchResponse<T>> {
  return fetchWithRetry<T>(url, {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json',
      ...options.headers,
    },
    body: JSON.stringify(data),
    ...options,
  });
}

/**
 * DELETE 请求封装
 */
export async function del<T>(
  url: string,
  options: FetchOptions = {}
): Promise<FetchResponse<T>> {
  return fetchWithRetry<T>(url, {
    method: 'DELETE',
    ...options,
  });
} 